1 module hip.gui.scroll_area; 2 import hip.gui.widget; 3 import hip.gui.button; 4 5 6 interface IRawScrollable 7 { 8 void onRawScroll(float[3] scroll); 9 } 10 11 class ScrollArea : Widget, IRawScrollable 12 { 13 private static IWidgetRenderer DebugRenderer() 14 { 15 import hip.api.graphics.g2d.renderer2d; 16 __gshared DebugWidgetRenderer dbgRenderer; 17 if(dbgRenderer is null) dbgRenderer = new DebugWidgetRenderer(HipColor(85,85,85,85)); 18 return dbgRenderer; 19 } 20 private IWidgetRenderer renderer; 21 private float scrollRate = -10, currentScroll = 0, lastScroll = 0; 22 23 this(int width, int height) 24 { 25 this.width = width; 26 this.height = height; 27 renderer = DebugRenderer(); 28 } 29 30 override Bounds getWorldBounds(){return Bounds(worldTransform.x, worldTransform.y, width, height);} 31 void setRenderer(IWidgetRenderer renderer) 32 { 33 assert(renderer !is null); 34 this.renderer = renderer; 35 } 36 37 void setScrollRate(float rate) 38 { 39 this.scrollRate = rate; 40 } 41 42 void setScroll(float scroll) 43 { 44 lastScroll = currentScroll; 45 currentScroll = scroll; 46 foreach(ch; children) 47 ch.onScroll([0,currentScroll,0], [0,lastScroll,0]); 48 } 49 50 void onRawScroll(float[3] scroll) 51 { 52 import hip.api; 53 setScroll(currentScroll + scroll[1]*scrollRate); 54 } 55 56 override void onRender() 57 { 58 import hip.api.graphics.g2d.renderer2d; 59 60 setStencilTestingEnabled(true); 61 setStencilTestingFunction(HipStencilTestingFunction.Always, 1, 0xFF); 62 setStencilOperation(HipStencilOperation.Keep, HipStencilOperation.Keep, HipStencilOperation.Replace); 63 setRendererColorMask(0,0,0,0); 64 fillRectangle(worldTransform.x, worldTransform.y, width, height); 65 setRendererColorMask(1,1,1,1); 66 setStencilTestingFunction(HipStencilTestingFunction.Equal, 1, 0xFF); 67 renderer.render(worldTransform.x, worldTransform.y, width, height); 68 foreach(ch; children) 69 ch.render(); 70 71 setStencilTestingEnabled(false); 72 } 73 } 74 75 import hip.gui.linear_layout; 76 class ScrollBar : LinearLayout 77 { 78 private 79 { 80 Button backward; 81 Button thumb; 82 Button forward; 83 } 84 85 ///Used to keep the layout size fixed 86 private Widget thumbFixer; 87 private int barSize = 50; 88 private int barRate = 1; 89 private float barScale = 1; 90 private int[2] buttonsDimensions; 91 92 void setButtonsSize(int width, int height) 93 { 94 forward.width = backward.width = width; 95 forward.height = backward.height = height; 96 } 97 98 void setBarSize(int size) 99 { 100 barSize = size; 101 setDimensionFromDirection(size); 102 } 103 104 void setTarget(int* target) 105 { 106 backward.setOnClick((){*target = *target - barRate;}); 107 forward.setOnClick((){*target = *target + barRate;}); 108 } 109 110 private void setDimensionFromDirection(int dimensionSize) 111 { 112 if(dir == LinearLayout.Direction.horizontal) 113 { 114 thumb.width = cast(int)(dimensionSize * barScale); 115 thumbFixer.width = dimensionSize; 116 } 117 else 118 { 119 thumb.height = cast(int)(dimensionSize * barScale); 120 thumbFixer.height = dimensionSize; 121 } 122 } 123 124 void setBarScale(int itemsShowing, int itemsCount) 125 { 126 barScale = cast(float)itemsShowing / itemsCount; 127 setDimensionFromDirection(this.barSize); 128 } 129 130 this(LinearLayout.Direction direction) 131 { 132 setDirection(direction); 133 thumbFixer = new Widget(); 134 thumbFixer.addChild(thumb = new Button(0,0, 50, 50)); 135 backward = new Button(0,0, 50, 50); 136 forward = new Button(0,0, 50, 50); 137 138 addChild(backward, thumbFixer, forward); 139 } 140 }